package com.pp.demo.common.util;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.Map;
import java.util.TreeMap;

public class SignatureUtils {

    private static final String HMAC_ALGORITHM = "HmacSHA256";
    private static final long TIMESTAMP_EXPIRY_MS = 60 * 60 * 1000; // 5分钟有效期

    /**
     * 生成签名
     * @param appId 应用ID
     * @param secret 密钥
     * @param timestamp 时间戳
     * @param nonce 随机数
     * @param params 请求参数
     * @return 签名结果
     */
    public static String generateSignature(String appId, String secret, String timestamp, String nonce, Map<String, String> params) {
        try {
            // 参数排序
            TreeMap<String, String> sortedParams = new TreeMap<>(params);

            // 构建签名字符串
            StringBuilder stringToSign = new StringBuilder();
            stringToSign.append(appId).append("&");
            stringToSign.append(timestamp).append("&");
            stringToSign.append(nonce).append("&");

            // 添加排序后的参数
            for (Map.Entry<String, String> entry : sortedParams.entrySet()) {
                stringToSign.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
            }

            // 移除最后一个&
            if (stringToSign.length() > 0) {
                stringToSign.deleteCharAt(stringToSign.length() - 1);
            }

            // 使用HMAC-SHA256算法生成签名
            Mac hmacSha256 = Mac.getInstance(HMAC_ALGORITHM);
            SecretKeySpec secretKey = new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), HMAC_ALGORITHM);
            hmacSha256.init(secretKey);
            byte[] hash = hmacSha256.doFinal(stringToSign.toString().getBytes(StandardCharsets.UTF_8));

            // Base64编码
            return Base64.getEncoder().encodeToString(hash);
        } catch (NoSuchAlgorithmException | InvalidKeyException e) {
            throw new RuntimeException("生成签名失败", e);
        }
    }

    /**
     * 验证签名
     * @param appId 应用ID
     * @param secret 密钥
     * @param timestamp 时间戳
     * @param nonce 随机数
     * @param signature 签名
     * @param params 请求参数
     * @return 验证结果
     */
    public static boolean verifySignature(String appId, String secret, String timestamp, String nonce,
                                          String signature, Map<String, String> params) {
        // 验证时间戳（防止重放攻击）
        long currentTime = System.currentTimeMillis();
        long requestTime = Long.parseLong(timestamp);
        if (Math.abs(currentTime - requestTime) > TIMESTAMP_EXPIRY_MS) {
            return false;
        }

        // 生成期望的签名并比对
        String expectedSignature = generateSignature(appId, secret, timestamp, nonce, params);
        return expectedSignature.equals(signature);
    }
}
